
import { _decorator, Component, Size, UITransform, Vec2, Vec3 } from 'cc';
import { ConfigKey, EventName, monster_base_config, monster_Refresh_config } from '../../manager/AppControll';
import { Move } from '../component/Move';
import { DataHelper } from '../../system/DataHelper';
import { Hp } from '../component/Hp';
import EvtManger from '../../tools/EvtManger';
import { Tools } from '../../tools/Tools';
import { CEventName, DamageStruct, FightControl, GameModel } from '../FightControl';
import { GameData } from '../../system/GameData';
import { MAnimation } from '../component/MAnimation';
import { SoundManager } from '../../manager/SoundManger';
import { LevelMonsterManager } from '../levelModel/LevelMonsterManager';
import { MonsterManager } from './MonsterManager';

const { ccclass, property } = _decorator;

export enum MonsterState {
    normal,
    die
}

@ccclass('MonsterOrigin')
export class MonsterOrigin extends Component {
    protected direction = 0;
    protected refreshConfig: monster_Refresh_config = null;
    protected baseConfig: monster_base_config = null;
    protected startPoint: Vec2;
    protected endPoint: Vec2;
    protected maxHp: number = 0;
    protected curHp: number = 0;
    protected attackedTime = 0;
    protected mState: MonsterState = MonsterState.normal;
    protected mLtAttackedTime: DamageStruct[] = [];
    protected mCurTime = 0;
    protected mBIsDeath = false;
    node: any;
    protected onLoad(): void {
        this.node.on(CEventName.MoveFinish, this.MoveFinish, this);
        this.node.on(CEventName.HpEmpty, this.Die, this);
    }

    InitMonster(config: monster_Refresh_config, base: monster_base_config) {
        this.refreshConfig = config;
        this.baseConfig = base;
        this.direction = this.GetDirection();
        this.node.active = true;
        this.InitHpComponent();
        this.InitMoveComponent();
        this.InitAnimiton();
    }

    get StarPoint() {
        return this.startPoint;
    }

    get EndPoint() {
        return this.endPoint;
    }

    get IsDeath() {
        return this.mBIsDeath;
    }

    InitMoveComponent() {

        let ltTemp = this.refreshConfig.lineRoute;
        let id = this.refreshConfig.lineRoute[0];

        if (ltTemp.length > 0) {
            id = ltTemp[Math.floor(Math.random() * (ltTemp.length))];
        }

        let lineConfig = DataHelper.GetMoveLineConfigById(id);
        let startPoint;
        let endPoint;

        if (this.direction == 1) {
            startPoint = new Vec2(lineConfig.leftPosition[0], lineConfig.leftPosition[1]);
            endPoint = new Vec2(lineConfig.rightPosition[0], lineConfig.rightPosition[1]);
        } else {
            startPoint = new Vec2(lineConfig.rightPosition[0], lineConfig.rightPosition[1]);
            endPoint = new Vec2(lineConfig.leftPosition[0], lineConfig.leftPosition[1]);
        }
        
        this.startPoint = startPoint;
        this.endPoint = endPoint;
        let speed = this.baseConfig.baseSpeed * this.refreshConfig.speedRatio;
        let move = this.node.getComponent(Move);
        if (move) {
            move.InitPoint(startPoint, endPoint, speed);
        } else {
            this.node.addComponent(Move).InitPoint(startPoint, endPoint, speed);
        }
        
        ltTemp = null;
        id = null;
        lineConfig = null;
        startPoint = null;
        endPoint = null;
    }

    InitHpComponent() {
        this.maxHp = this.baseConfig.baseBlood * this.refreshConfig.BloodVolumeRatio;
        this.curHp = this.maxHp;
        if (this.node.getComponent(Hp)) {
            this.node.getComponent(Hp).InitHp(this.maxHp);
            return;
        }
        this.node.addComponent(Hp).InitHp(this.maxHp);
    }
    //
        SkeletalAnimationComponent
    InitAnimiton() {
        let path = this.baseConfig.monsterRes;
        this.node.getChildByName("Ani").getComponent(UITransform).contentSize = new Size(this.baseConfig.monsterSize[0], this.baseConfig.monsterSize[0])
        if (!this.node.getComponent(MAnimation)) {
            this.node.addComponent(MAnimation).InitMAnimation(path, this.baseConfig);
        } else {
            this.node.getComponent(MAnimation).InitMAnimation(path, this.baseConfig);
        }
        path = null;
    }

    GetDirection(): number {
        let result = 0;
        if (!this.refreshConfig) return;
        if (this.refreshConfig.monsterMovement == 0) {
            result = 1;
        } else if (this.refreshConfig.monsterMovement == 1) {
            result = -1;
        } else if (this.refreshConfig.monsterMovement == 2) {
            let ran = Math.random();
            if (ran > 0.5) {
                result = 1;
            } else {
                result = -1;
            }
        }
        return result;
    }

    Attacked(dmg: DamageStruct) {
        
        let temp: DamageStruct = {

            isCriticalHit: dmg.isCriticalHit,
            damage: dmg.damage,
            time: dmg.time + this.mCurTime
        }


        this.mLtAttackedTime.push(temp);
    }

    protected update(dt: number): void {


        if (GameData.isPause) return;
        if (this.mBIsDeath) return;

        this.mCurTime += dt;
        
        if (this.mLtAttackedTime.length == 0) {
            return;
        }
        
        for (let i = 0; i < this.mLtAttackedTime.length; i++) {

            if (this.mCurTime >= this.mLtAttackedTime[i].time) {

                if (this.getComponent(MAnimation)) {
                    this.getComponent(MAnimation).BeAttack();
                }

                if (this.getComponent(Hp)) {
                    this.getComponent(Hp).takeDamage(this.mLtAttackedTime[i]);
                }
                
                Tools.RemoveElementByVaule(this.mLtAttackedTime, this.mLtAttackedTime[i]);
            }
        }
    }
    getComponent(MAnimation: typeof MAnimation) {
        throw new Error('Method not implemented.');
    }

    Die() {
        this.mState = MonsterState.die;
        this.node.getChildByName("lockTarget").active = false;
        this.node.getComponent(Move).Speed *= 0;
        this.node.getComponent(MAnimation).PlayDeath(() => {
            this.node.active = false;
            this.node.destroy();
        })
        this.scheduleOnce(() => {
            this.node.active = false;
            this.node.destroy();
        }, 1.5);
        SoundManager.Instance<SoundManager>().PlayEffect("death/" + this.baseConfig.deathAudio, Number.parseFloat(DataHelper.GetConfigByKey(ConfigKey.monsterVolume).value));
        if (DataHelper.GetMonsterRefreshConfigById(DataHelper.GetMonsterRefreshByAuto().stageID + 1)) {
            GameData.playerData.KillMonsters++;
        }
        let skinGold = DataHelper.GetSkinBuffGold();
        GameData.AddGold(this.baseConfig.baseGold * this.refreshConfig.dropGoldRatio * skinGold);
        GameData.AddHonor(this.baseConfig.baseHonor * this.refreshConfig.dropHonorRatio);
        Tools.RemoveElementByVaule(Tools.GetLtMonster() as [], this.node);
        EvtManger.do(EventName.monsterDeath, this.node);
    }
    scheduleOnce(arg0: () => void, arg1: number) {
        throw new Error('Method not implemented.');
    }

    MoveFinish() { //
        EvtManger.do(EventName.monsterDeath, this.node);
        Tools.RemoveElementByVaule(Tools.GetLtMonster() as [], this.node);
        MonsterManager.normalMonsterPool.put(this.node);
    }

    BeLock() {
        this.node.getChildByName("lockTarget").active = true;
        this.node.getComponent(Hp).ShowHp();
    }

    BeNormal() {
        this.node.getChildByName("lockTarget").active = false;
        this.node.getComponent(Hp).HideHp();
    }

    protected onDestroy(): void {
        this.node.off(CEventName.HpEmpty, this.Die);
        this.node.off(CEventName.MoveFinish, this.MoveFinish);
    }
}

